import struct

def hex_to_bin_array(hex):
    hex = bin(hex)
    hex = hex.replace('0b','')
    arr = []
    for i in hex:
        arr.append(i)
    return arr
def bin_array_to_hex(bin_array):
    #x =  '0b'
    x=''
    for b in bin_array:
        x = x +str(b)
    return int(x,2)
def is_one_or_zero(i):
    i = int(i)
    if i is not 1 and i is not 0:
        return False
    return True

class Gdt:
    def __init__(self):
        self.core = [0]*64
        
    def set_bit(self,index,val):
        if is_one_or_zero(val):
            corep = self.core[::-1]
            corep[index] = str(int(val))
            self.core = corep[::-1]

    def set_g(self,g):
        self.set_bit(55,g)
    def set_s(self,s):
        self.set_bit(44,s)
    def set_dpl(self,dpl):
        dpl = bin(dpl)
        dpl = dpl.replace('0b','')
        arr = [0]*2
        if len(dpl) is 1:
            dpl = '0'+dpl
        for i in range(0,2):
            arr[i] = dpl[i]
        arr = arr[::-1]
        for i in range(45,47):
            self.set_bit(i,arr[45-i])
    def set_db(self,db):
        self.set_bit(54,db)
    def set_l(self,l):
        self.set_bit(53,l)
    def set_avl(self,avl):
        self.set_bit(52,avl)
    def set_p(self,p):
        self.set_bit(47,p)
    def set_type(self,x,e,w,a):
        # todo
        self.set_bit(40,x)
        self.set_bit(41,e)
        self.set_bit(42,w)
        self.set_bit(43,a)

    def set_base(self,base):
        # todo
        # 段基址为[16-39,56-63]
        base = bin(base)
        base = base.replace('0b','')
        arr = [0]*32
        zero_attr = '';
        for i in range(0,32 - len(base)):
            zero_attr += '0'
        base = zero_attr + base;
        array = []
        for i in base:
            array.append(i)
        base = array[::-1]
        for index in range(0,24):
            self.set_bit(16 + index,base[index])
        for index in range(24,32):
            self.set_bit(32+index,base[index])

    def set_offset(self,offset):
        # 0-15 48-51
        offset = bin(offset)
        offset = offset.replace('0b','')
        arr = [0]*20
        zero_attr = '';
        for i in range(0,20 - len(offset)):
            zero_attr += '0'
        offset = zero_attr + offset;
        array = []
        for i in offset:
            array.append(i)
        offset = array[::-1]
        for i in range(0,16):
            self.set_bit(i,offset[i])
        for i in range(16,20):
            self.set_bit(32+i,offset[i])

    def print_desc(self):        
        # 基址=[hex]
        # 界限=[hex]
        # [32/64]位,[字节/4KB]粒度
        # [代码段/数据段],特权级别[0-3]
        # [X-E-W/X-C-R][000]
        # 是否可执行-扩展方向-是否可写-是否特权级依从-是否可读
        self.print_hex()

        # 低字节序反转
        corep = self.core[::-1]
        # 段基址为[16-39,56-63]
        base = []
        for i in range(16,40):
            base.append(corep[i])
        for i in range(56,64):
            base.append(corep[i])
        base = base[::-1]
        print('段基地址为:'+hex(bin_array_to_hex(base)))
        g = int(corep[55])
        g_desc = '字节'
        if g is 1:
            g_desc = '4KB'
        # 0-15 48-51
        offset=[]
        for i in range(0,16):
            offset.append(corep[i])
        for i in range(48,52):
            offset.append(corep[i])
        offset = offset[::-1]
        offset = bin_array_to_hex(offset)
        if g is 1:
            offset = offset * 0x1000 + 0xFFF
        offset_k = offset / 1024
        offset_m = offset_k / 1024
        offset_g = offset_m / 1024
        print('界限:'+hex(offset)+' '+str(offset_k) + 'KB ' + str(offset_m) + 'MB '+ str(offset_g) +'GB')
        print('G='+str(g) + ' 粒度为:'+g_desc)
        s = int(corep[44])
        s_desc = 'S=0 系统段'
        if s is 1:
            s_desc = 'S=1 代码段或数据段'
        print(s_desc)
        p = int(corep[47])
        p_desc = 'P=1 该代码段目前位于内存中'
        if p is 0:
            p_desc = 'P=0 该代码段目前内存中不存在'
        print(p_desc)
        # dpl [45-46]
        dpl = []
        for i in range(45,47):
            dpl.append(corep[i])
        dpl = bin_array_to_hex(dpl)
        print('DPL(特权级)='+str(dpl))
        db = int(corep[54])
        db_desc = 'D=16位/B=SP'
        if db is 1:
            db_desc = 'D=32位/B=ESP'
        print(db_desc)
        # type [40-43]
        type = 'TYPE='
        array_type = []
        for i in range(40,44):
            array_type.append(corep[i])
        array_type = array_type[::-1]
        for i in array_type:
            type += str(i)
        print(type)
        print('L='+corep[53])
        print('AVL='+corep[52])

    def print_hex(self):
        print("HEX:"+hex(bin_array_to_hex(self.core)))

    def load_from_hex(self,hex):
        array = hex_to_bin_array(hex)
        start = 64 - len(array)
        for i in range(0,len(array)):
            self.core[i+start] = array[i]
    def print_bin(self,split = ' ',len= 8):
        p = 1
        for i in range(0,64):
            print(self.core[i],end='')
            if p%len is 0:
                print(split,end='')
            p = p+1
        print(end='\n')


x = Gdt()
x.load_from_hex(0x004F9AFFFFFFFFFF)
# x.print_bin()
# x.print_hex()
x.print_desc()

x.set_dpl(3)
x.set_base(0xfffff8)
x.set_offset(0xf)
x.set_l(1)
x.print_desc()